package org.scboy.rbac.service.imp;

import java.util.Date;
import java.util.List;

import org.scboy.common.utils.CodeUtil;
import org.scboy.coobi.sql.factory.EntityFactory;
import org.scboy.rbac.dao.RbacOrgDao;
import org.scboy.rbac.dao.RbacOrgResourceDao;
import org.scboy.rbac.dao.RbacOrgUserDao;
import org.scboy.rbac.loads.LoadOrg;
import org.scboy.rbac.service.OrgService;
import org.scboy.utils.caches.rbac.entity.OrgEntity;
import org.scboy.utils.entitys.coobi.Model;
import org.scboy.utils.entitys.coobi.Page;
import org.scboy.utils.enums.coobi.OrderType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.hutool.core.util.StrUtil;

@Service
public class OrgServiceImp implements OrgService {

	@Autowired
	EntityFactory factory;
	
	@Autowired
	LoadOrg cache;
	
	@Override
	public Page page(Model model) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		return dao.queryPage(model);
	}

	@Override
	public Long getMaxIndex(String parentId) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		Long orgIndex=1L;
		Model maxModel=dao.maxIndex(parentId);
		if(maxModel!=null&& maxModel.getLong("orgIndex")!=null){
			orgIndex=maxModel.getLong("orgIndex")+1;
		}
		return orgIndex;
	}

	@Override
	public List<Model> getChilds(Model params) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		List<Model> result=dao.queryList(params);
		for (Model model : result) {
			params.add("parentId", model.getString("id"));
			if(dao.count(params)>0){
				model.put("isLeaf", false);
				model.put("isParent", true);
			}else{
				model.put("isLeaf", true);
				model.put("isParent", false);
			}
		}
		return result;
	}
	
	/**
	 * 获取子组织数量
	 * @param parentId
	 * @return
	 */
	public Long getChildCount(String parentId) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		return dao.count(Model.create().add("parentId", parentId));
	}
	
	@Override
	public Model get(String id) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		return dao.get(Model.create().add("id", id));
	}

	@Override
	@Transactional
	public boolean add(Model model) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		String parentId=model.getString("parentId");
		Model parentOrg=get(parentId);
		if(parentOrg==null){
			parentOrg=Model.create();
			parentOrg.add("orgCode", "");
			parentOrg.add("orgLocation", "");
		}
		Long orgIndex=getMaxIndex(parentId);
		model.add("orgSort", orgIndex);
		model.add("orgCode", parentOrg.getString("orgCode")+CodeUtil.getCurNo(orgIndex, 3, "0"));
		model.add("orgIndex",orgIndex);
		model.add("orgLocation",parentOrg.getString("orgLocation")+model.getString("orgName"));
		model.add("orgShortName", model.getString("orgLocation"));
		model.add("addTime", new Date());
		model.add("editTime", new Date());
		int result=dao.insert(model);
		if(result>0){
			cache.update(model.toEntity(OrgEntity.class));
			return true;
		}else{
			return false;
		}
	}

	@Override
	public boolean update(Model model) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		model.add("editTime", new Date());
		int result=dao.update(model);
		if(result>0){
			cache.updateByKey(model.getString("id"));
			return true;
		}else{
			return false;
		}
	}

	@Override
	@Transactional
	public boolean delete(String id) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		RbacOrgResourceDao orgResDao=factory.getDao(RbacOrgResourceDao.class);
		RbacOrgUserDao orgUserDao=factory.getDao(RbacOrgUserDao.class);

		//组织下有子组织，不让删除
		if(getChildCount(id)>0){
			return false;
		}
		
		//组织下有用户，不让删除
		if(orgUserDao.count(Model.create().add("orgId", id))>0) {
			return false;
		}
		
		//删除组织角色关联
		orgResDao.delete(Model.create().add("orgId", id));
		
		int result=dao.delete(Model.create().add("id", id));
		if(result>0){
			cache.updateByKey(id);
			return true;
		}else{
			return false;
		}
	}

	@Override
	@Transactional
	public boolean merge(Model model) {
		RbacOrgResourceDao orgResDao=factory.getDao(RbacOrgResourceDao.class);
		RbacOrgUserDao orgUserDao=factory.getDao(RbacOrgUserDao.class);
		String firstId=model.getString("firstId");
		String secondId=model.getString("secondId");
		//合并的组织不能为空
		if(StrUtil.isEmpty(firstId)){
			return false;
		}
		if(StrUtil.isEmpty(secondId)){
			return false;
		}
		//不能与自己的上级组织合并
		if(firstId.indexOf(secondId)>-1 || secondId.indexOf(firstId)>-1 ) {
			return false;
		}
		if(add(model)){
			//移动组织角色到新组织
			orgResDao.update(Model.create().add("orgId", model.getString("id")),Model.create().add("orgId", firstId));
			orgResDao.update(Model.create().add("orgId", model.getString("id")),Model.create().add("orgId", secondId));
			//移动组织人员到新组织
			orgUserDao.update(Model.create().add("orgId", model.getString("id")),Model.create().add("orgId", firstId));
			orgUserDao.update(Model.create().add("orgId", model.getString("id")),Model.create().add("orgId", secondId));
			//重构组织结构
			grenAll(model.getString("id"));

			return true;
		}else{
			return false;
		}
	}

	@Override
	public boolean checkCode(String code) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		if(dao.count(Model.create().add("orgCode", code))>0){
			return true;
		}else{
			return false;
		}
	}

	@Override
	public Page getUsers(Model model) {
		RbacOrgUserDao dao=factory.getDao(RbacOrgUserDao.class);
		return dao.queryPage(model);
	}

	@Override
	public List<Model> getOrgs(String parentId) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		Model model=get(parentId);
		Model params=new Model();
		if(model!=null) {
			params.add("orgCode", model.getString("orgCode")+"%");
		}
		return dao.queryList(params);
	}
	
	@Override
	public List<Model> getOrgs(Model model) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		Model orgModel=get(model.getString("parentId"));
		Model params=new Model();
		if(orgModel!=null) {
			params.add("orgCode", orgModel.getString("orgCode")+"%");
		}
		if(model.getString("level")!=null&&!"".equals(model.getString("level"))){
			params.add("level", model.getString("level").split(","));
		}
		return dao.findLastOrg(params);
	}

	@Override
	@Transactional
	public boolean sort(String id, int type) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		Model model=dao.get(Model.create().add("id", id));
		Model lastModel=null;
		String sortKey="orgSort";
		String idKey="id";
		//降序
		if(type==0) {
			//查询下面一个系统
			lastModel=dao.get(Model.create().GT(sortKey, model.getInt(sortKey)).add("parentId", model.get("parentId")).orderBy(sortKey));
			
		}else {
			//升序
			lastModel=dao.get(Model.create().LT(sortKey, model.getInt(sortKey)).add("parentId", model.get("parentId")).orderBy(sortKey,OrderType.DESC));
			
		}
		if(lastModel!=null) {
			dao.update(Model.create().add(sortKey, lastModel.getInt(sortKey)),Model.create().add(idKey, id));
			dao.update(Model.create().add(sortKey, model.getInt(sortKey)),Model.create().add(idKey, lastModel.getString(idKey)));
		}
		return true;
	}

	@Override
	@Transactional
	public boolean grenAll(String parentId) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		List<Model> modelList=dao.select(Model.create().add("parentId", parentId).orderBy("orgSort"));
		int index=0;
		for (Model model : modelList) {
			gren(model,index);
			grenAll(model.getString("id"));
			index++;
		}

		//移除所有组织缓存
		cache.removeAll();
		
		//重新加载组织缓存
		List<Model> list=dao.select(Model.create().addRc("id").addRc("orgName").addRc("orgLocation").addRc("orgShortName"));
		for (Model area : list) {
			cache.update(area.toEntity(OrgEntity.class));
		}
		return true;
	}
	
	
	public void gren(Model model,long index){
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		String parentId=model.getString("parentId");
		Model parentOrg=get(parentId);
		if(parentOrg==null){
			parentOrg=Model.create();
			parentOrg.add("orgCode", "");
			parentOrg.add("orgLocation", "");
		}
		model.add("orgSort", index);
		model.add("orgCode", parentOrg.getString("orgCode")+CodeUtil.getCurNo(index, 3, "0"));
		model.add("orgIndex",index);
		model.add("orgLocation",parentOrg.getString("orgLocation")+model.getString("orgName"));
		model.add("orgShortName", model.getString("orgLocation"));
		model.add("addTime", new Date());
		model.add("editTime", new Date());
		dao.update(model);
	}

	@Override
	public List<Model> tree(Model params) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		List<Model> result=dao.select(params);
		for (Model model : result) {
			
			model.add("label", model.getString("orgShortName"));
			
			params.add("parentId", model.getString("id"));
			List<Model> children=tree(params);
			model.add("children", children);
		}
		return result;
	}

	@Override
	public Model getTop(String id) {
		RbacOrgDao dao=factory.getDao(RbacOrgDao.class);
		Model data= dao.getTop(Model.create().add("id", id));
		if(dao.count(Model.create().add("parentId", id))>0){
			data.put("isLeaf", false);
			data.put("isParent", true);
		}else{
			data.put("isLeaf", true);
			data.put("isParent", false);
		}
		return data;
	}
	
}
